package org.spring.springboot.app.base;

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.spring.springboot.util.BeanValidators;
import org.springframework.beans.factory.annotation.Autowired;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

@ApiModel("结构")
public class R<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "逻辑代码")
    private Integer code = 0;

    @ApiModelProperty(value = "消息提示")
    private String message = "成功";

    @ApiModelProperty(value = "消息提示列表")
    private List<Error> messages = null;

    @ApiModelProperty(value = "数据")
    private T data;

    public R() {
        super();
    }

    public R(Type type) {
        super();
        this.code = type.getCode();
        this.message = type.getMessage();
    }

    public R(Integer code, String message) {
        super();
        this.code = code;
        this.message = message;
    }

    public R(Integer code, String message, T data) {
        super();
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public R setType(Type type) {
        this.code = type.getCode();
        this.message = type.getMessage();
        return this;
    }

    public Integer getCode() {
        return code;
    }

    public R setCode(Integer code) {
        this.code = code;
        return this;
    }

    public String getMessage() {
        return message;
    }

    public R setMessage(String message) {
        this.message = message;
        return this;
    }

    public T getData() {
        return data;
    }

    public R setData(T data) {
        this.data = data;
        return this;
    }

    public List<Error> getMessages() {
        return messages;
    }

    public R setMessages(List<Error> messages) {
        this.messages = messages;
        return this;
    }

    public void addMessage(String key, String value) {
        if (messages == null) {
            messages = new ArrayList<Error>();
        }
        messages.add(new Error(key,value));
    }

    @JsonIgnore
    @ApiModelProperty(hidden = true)
    private Validator validator;

    /**
     * 服务端参数有效性验证
     *
     * @param object 验证的实体对象
     * @param groups 验证组
     * @return 验证成功：返回true；严重失败：将错误信息添加到 message 中
     */
    public boolean valid(Object object, Class<?>... groups) {
        if (validator == null) {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            validator = factory.getValidator();
        }
        try {
            BeanValidators.validateWithException(validator, object, groups);
        } catch (ConstraintViolationException ex) {
            List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, "|_|");
            List<Error> errors = new ArrayList<Error>();
            for(String l : list){
                String[] lp = l.split("\\|_\\|");
                Error e = new Error(lp[0],lp[1]);
                errors.add(e);
            }
            this.setType(Type.ParamValidateFail);
            if (this.messages == null || list.isEmpty()) {
                this.setMessages(errors);
            } else {
                this.messages.addAll(errors);
            }
            return false;
        }
        return true;
    }

    public R success() {
        this.code = 0;
        this.message = "成功";
        return this;
    }
    public R fail() {
        this.code = 100;
        this.message = "失败";
        return this;
    }
}
